package bierki;

import java.awt.*;
import java.awt.geom.*;
import java.util.*;

/**
 * Klasa abstrakcyjna reprezentująca podstawową funkcjonalność bierki szachowej
 * potrafi sie sama narysować, sprawdzić bicia i szach.
 * @author Konrad Sobczak 
 * @author Kamil Nowak
 */

public abstract class Bierka {

	private Image twarz;
	private int symbol; //nie enum bo latwiej jest potem sterowac jak biale moga byc ujemne a czarne dodatnie
	protected BierkaTyp typ;
	protected BierkaKolor kolor;
	
	protected int x;
	protected int y;
	/**
	 * 
	 * @param sciezkaiNazwaObrazka reprezentuje sciezke dostepu do pliku który będzie stanowił wygląd bierki
	 * 
	 * @param symbol jest obsolete
	 */
	public Bierka(String sciezkaiNazwaObrazka, int symbol){
		
		//zaladuje obrazek
		
		
		twarz = Toolkit.getDefaultToolkit().getImage(sciezkaiNazwaObrazka);
		MediaTracker trop=new MediaTracker(new Panel());
		trop.addImage(twarz,0);
		try{
			trop.waitForID(0);
		}
		catch(Exception ex){
			
		}
		//dostanie swoj symbol
		this.symbol = symbol;
	}
	
	/**
	 * 
	 * @param obrazek sciezka do obrazka 
	 * @param typ zeby wiedzieć jaką bierkę tworzymy (enum)
	 * @param kolor biały lub czarny (enum)
	 * @param x pozycja na planszy wzgledem osi ox
	 * @param y pozycja na planszy wzgledem osi oy
	 */
	public Bierka(String obrazek, BierkaTyp typ, BierkaKolor kolor,int x, int y) {
		//this.twarz =  Toolkit.getDefaultToolkit().getImage(Thread.currentThread().getContextClassLoader().getResource(obrazek));
		this.twarz =  Toolkit.getDefaultToolkit().getImage(obrazek);
		MediaTracker trop=new MediaTracker(new Panel());
		trop.addImage(twarz,0);
		try{
			trop.waitForID(0);
		}
		catch(Exception ex){
			
		}
		this.typ = typ;
		this.kolor = kolor;
		this.x = x;
		this.y = y;
	}
	
	/**
	 * Nieużywany konstruktor
	 * @param typ - typ bierki
	 * @param kolor - kolor bialy albo czarny
	 * @param x - pozycja x na szachownicy	
	 * @param y - pozycja y na szachownicy
	 */
	public Bierka(BierkaTyp typ, BierkaKolor kolor,int x, int y) {
		this.typ = typ;
		this.kolor = kolor;
		this.x = x;
		this.y = y;
	}
	
	/**
	 * jest obsolete
	 * @return zwraca symbol
	 */
	public int getSymbol(){
		return this.symbol;
	}
	
	/**
	 * Rysuje bierke na podanym Graphicsie
	 * @param g - Graphics na którym będziemy rysować
	 * @param x - współrzedna x rysunku
	 * @param y - współrzędna y rysunku
	 * @param grubosc - wysokość rysunku
	 * @param szerokosc - szerokość rysunku
	 */
	public void narysujSie(Graphics g,int x,int y, int grubosc, int szerokosc){
		g.drawImage(twarz,x,y,grubosc,szerokosc,null);
	}
	
	/**
	 * 
	 * @return zwraca kolor bierki (enum)
	 */
	public BierkaKolor getKolor() {
		return kolor;
	}

	/**
	 * 
	 * @return zwraca typ bierki (enum)
 	 */
	public BierkaTyp getTyp() {
		return typ;
	} 
	
	/**
	 * 
	 * @return zwraca pozycje x na szachownicy
	 */
	public int getX() {
		return x;
	}

	/**
	 * 
	 * @return zwraca pozycje y na szachownicy
	 */
	public int getY() {
		return y;
	}

	/**
	 * Rusza bierką, ale tylko w niej samej, należy jeszcze zmienić pozycje bierki 
	 * na szacjownicy 
	 * @param x nowa współrzędna x bierki
	 * @param y nowa współrzędna y bierki
	 */
	public void move(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	/**
	 * Sprawdza czy nowa pozycja bierki nie wypada za szachownicą
	 * @param x współrzędna x nowej pozycji bierki
	 * @param y współrzędna y nowej pozycji bierki
	 * @return zwraca true/false.
	 */
	public boolean pozaSzachownica(int x, int y) {
		
		return !(x>=0 && y>=0 && y<=7 && x<=7); 
		
	}
	
	/**
	 * Sprawdza możliwe bicia Bierki
	 * @param bierka bierka na której sprawdzamy
	 * @return zwraca prawdę lub fałsz
	 */
	public boolean sprawdzBicie(Bierka bierka) {
		return bierka != null && (bierka.getKolor() == kolor || bierka.getTyp() == BierkaTyp.KROL);
		
	}
	
	/**
	 * Sprawdza na podstawie sytuacji na szachownicy i pozycji króla czy występuje
	 * szach
	 * @param szachownica - tablica/macierz Bierek, reprezentacja szachownicy
	 * @param xk - końcowe położenie bierki która chce wykonać ruch
	 * @param yk - jw. tyle że współrzędna y
	 * @param krol - król dla, którego chcemy sprawdzić szach.
	 * @return - prawda jeśli jest szach, fałsz jeśli nie ma
	 */
	public boolean sprawdzSzach(Bierka[][] szachownica, int xk, int yk, Krol krol) {
		
		Bierka[][] szachownicaTmp = new Bierka[8][8];
		multiArrayCopy(szachownica,szachownicaTmp);
		szachownicaTmp[x][y] = null; 
		szachownicaTmp[xk][yk] = this;
		return krol.szach(szachownicaTmp);
	}
	
	protected void multiArrayCopy(Object[][] source, Object[][] destination)
	{
	for (int a=0;a<source.length;a++)
		{
		System.arraycopy(source[a],0,destination[a],0,source[a].length);
		}
	}
	
	
	public abstract boolean sprawdzRuch(Bierka[][] szachownica,int x, int y);
	/**
	 * Metoda abstrakcyjna przeciążana przez wszystkie dziedziczące z ObiektRysowany
	 * sprawdza czy ruch jest dozwolony
	 **/
	public abstract boolean sprawdzRuch(Bierka[][] szachownica,int x, int y, Krol krol);
	
	/*Dzialac to bedzie tak: metoda zwroci tablice puntkow na ktore moze sie bierka ruszyc
	 * lub bic. Jezeli punkt koncowy bedzie sie znajdowal w tej tablicy to znaczy ruch jest
	 * prawidlowy, jesli nie - nieprawidlowy. Wywolywac to wszystko bedzie GameManager
	 * ale dzis nie zdazylem tego napisac. W ten sposob bedzie mozna rowniez wykrywac szach
	 * i pewnie pomoze przy macie. Nie wiem tylko co zrobi z pionkami ktore inaczej bija
	 * a inaczej sie ruszaja??? Masz jakis pomysl? Poki co zrobilem ze bicia Point2D.Double
	 * a ruchy Point2D.Float
	 */
	public abstract Vector<Point2D> validateMove(Bierka[][] plansza,int xp, int yp);
	
}
